package com.dianrong.common.uniauth.client.config;

import java.util.Map;

import javax.annotation.Resource;

import org.jasig.cas.client.session.SingleSignOutFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.util.Assert;

import com.dianrong.common.uniauth.client.custom.SSExceptionTranslationFilter;
import com.dianrong.common.uniauth.common.client.DomainDefine;

import lombok.extern.slf4j.Slf4j;

/**
 * uniauth 针对spring boot的集成配置对象 一般做法是直接继承该类作为spring security配置
 * <p>
 * 如果需要 重写自定义configure（HttpSecurity http）<br>
 * 请不要忘记: 调用该类中的配置：super.configure(HttpSecurity http)
 * <p>
 * 
 * @author wanglin
 */
@Slf4j
public class UniauthSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ConfigureBeanCreator beanCreator;

    @Resource(name = "sas")
    private SessionAuthenticationStrategy sas;

    @Resource(name = "uniauthConfig")
    private Map<String, String> uniauthConfig;

    @Autowired
    private DomainDefine domainDefine;

    @Autowired
    private CasAuthenticationEntryPoint casAuthEntryPoint;

    /**
     * configure security filter chain for uniauth
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        Assert.notNull(beanCreator, "UniauthSecurityConfig need managed by spring");
        log.info("start uniauth security configure");

        // <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        http.authorizeRequests().anyRequest().authenticated();

        // session management configure
        http.sessionManagement().sessionAuthenticationStrategy(sas).invalidSessionUrl(getInvalidSessionUrl());

        // logout delete cookie and csrf configure
        http.logout().deleteCookies("JSESSIONID").and().csrf().disable();

        // filter configure
        http.addFilter(beanCreator.create(ConcurrentSessionFilter.class));
        http.addFilter(beanCreator.create(CasAuthenticationFilter.class));
        http.addFilterBefore(beanCreator.create(LogoutFilter.class), LogoutFilter.class);
        http.addFilterAfter(beanCreator.create(SSExceptionTranslationFilter.class), ExceptionTranslationFilter.class);
        http.addFilterBefore(beanCreator.create(SingleSignOutFilter.class), CasAuthenticationFilter.class);

        // entry-point configure
        http.exceptionHandling().authenticationEntryPoint(casAuthEntryPoint);
        log.info("finish uniauth security configure");
    }

    /**
     * #{uniauthConfig['cas_server']}/login?service=#{uniauthConfig['domains.'+domainDefine.domainCode]}/login/cas
     * 
     * @return
     */
    private String getInvalidSessionUrl() {
        String invalidSessionUrl = uniauthConfig.get("cas_server") + "/login?service=" + uniauthConfig.get("domains." + domainDefine.getDomainCode()) + "/login/cas";
        log.info("invalidSessionUrl is " + invalidSessionUrl);
        return invalidSessionUrl;
    }
}
